#include "ascii.h"

int gumbo_ascii_strcasecmp(const char *s1, const char *s2) {
  int c1, c2;
  while (*s1 && *s2) {
    c1 = (int)(unsigned char) gumbo_ascii_tolower(*s1);
    c2 = (int)(unsigned char) gumbo_ascii_tolower(*s2);
    if (c1 != c2) {
      return (c1 - c2);
    }
    s1++;
    s2++;
  }
  return (((int)(unsigned char) *s1) - ((int)(unsigned char) *s2));
}

int gumbo_ascii_strncasecmp(const char *s1, const char *s2, size_t n) {
  int c1, c2;
  while (n && *s1 && *s2) {
    n -= 1;
    c1 = (int)(unsigned char) gumbo_ascii_tolower(*s1);
    c2 = (int)(unsigned char) gumbo_ascii_tolower(*s2);
    if (c1 != c2) {
      return (c1 - c2);
    }
    s1++;
    s2++;
  }
  if (n) {
    return (((int)(unsigned char) *s1) - ((int)(unsigned char) *s2));
  }
  return 0;
}

const unsigned char _gumbo_ascii_table[0x80] = {
  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x03,0x03,0x01,0x03,0x03,0x01,0x01,
  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x28,0x28,0x28,0x28,0x28,0x28,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
  0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,
  0x00,0x50,0x50,0x50,0x50,0x50,0x50,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,
};

// Table generation code.
// clang -DGUMBO_GEN_TABLE=1 ascii.c && ./a.out && rm a.out
#if GUMBO_GEN_TABLE
#include <stdio.h>

int main() {
  printf("const unsigned char _gumbo_ascii_table[0x80] = {");
  for (int c = 0; c < 0x80; ++c) {
    unsigned int x = 0;
    // https://infra.spec.whatwg.org/#ascii-code-point
    if (c <= 0x1f)
      x |= GUMBO_ASCII_CNTRL;
    if (c == 0x09 || c == 0x0a || c == 0x0c || c == 0x0d || c == 0x20)
      x |= GUMBO_ASCII_SPACE;
    if (c >= 0x30 && c <= 0x39)
      x |= GUMBO_ASCII_DIGIT;
    if ((c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x46))
      x |= GUMBO_ASCII_UPPER_XDIGIT;
    if ((c >= 0x30 && c <= 0x39) || (c >= 0x61 && c <= 0x66))
      x |= GUMBO_ASCII_LOWER_XDIGIT;
    if (c >= 0x41 && c <= 0x5a)
      x |= GUMBO_ASCII_UPPER_ALPHA;
    if (c >= 0x61 && c <= 0x7a)
      x |= GUMBO_ASCII_LOWER_ALPHA;
    printf("%s0x%02x,", (c % 16 == 0? "\n  " : ""), x);
  }
  printf("\n};\n");
  return 0;
}
#endif
